/*
 * Copyright (c) 2022 ASR Microelectronics (Shanghai) Co., Ltd. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cmsis_os2.h"
#include "kal.h"
#include "los_event.h"
#include "los_membox.h"
#include "los_memory.h"
#include "los_interrupt.h"
#include "los_mux.h"
#include "los_queue.h"
#include "los_sem.h"
#include "los_swtmr.h"
#include "los_task.h"
#include "los_timer.h"
#include "los_debug.h"
#include "los_arch_interrupt.h"

UINT32 LOS_SemPendingNoTask(UINT32 semHandle)
{
    UINT32 intSave,retVal;
    LosSemCB *semOnCheck = GET_SEM(semHandle);

    if (semHandle >= LOSCFG_BASE_IPC_SEM_LIMIT) {
        return LOS_ERRNO_SEM_INVALID;
    }

    intSave = LOS_IntLock();

    if (LOS_ListEmpty(&semOnCheck->semList))
    {
        retVal = LOS_OK;
    }
    else
    {
        retVal = LOS_NOK;
    }

    LOS_IntRestore(intSave);
    return retVal;
}

osStatus_t osSemaphorePendingNoTask(osSemaphoreId_t semaphore_id)
{
    UINT32 uwRet;

    if (OS_INT_ACTIVE) {
        return osErrorISR;
    }

    if (semaphore_id == NULL) {
        return osErrorParameter;
    }

    uwRet = LOS_SemPendingNoTask(((LosSemCB *)semaphore_id)->semID);
    if(uwRet == LOS_OK)
        return osOK;
    else
        return osError;
}

#if (LOSCFG_MEM_MUL_POOL == 1)
extern VOID *g_poolHead;
UINT32 LOS_PoolHeadFreeSize(VOID)
{
    LOS_MEM_POOL_STATUS status = {0};

    if (LOS_MemInfoGet((struct OsMemPoolHead *)g_poolHead, &status) == LOS_NOK) {
        return OS_ERROR;
    }

    return  status.totalFreeSize;
}
#endif

/* ****************************************************************************
Function    : HalGetCpuCycle
Description : Get System cycle count
Input       : none
output      : cntHi  --- CpuTick High 4 byte
              cntLo  --- CpuTick Low 4 byte
return      : none
**************************************************************************** */
LITE_OS_SEC_TEXT_MINOR VOID HalGetCpuCycle(UINT32 *cntHi, UINT32 *cntLo)
{
    UINT64 ticks;
    UINT32 intSave = LOS_IntLock();
    ticks = SysTimer_GetLoadValue();

    *cntHi = ticks >> SHIFT_32_BIT;
    *cntLo = ticks & CYCLE_CHECK;

    LOS_IntRestore(intSave);
    return;
}


WEAK VOID HalDelay(UINT32 ticks)
{
    return;
}

WEAK UINT64 HalGetExpandTick(VOID)
{
    return LOS_OK;
}

WEAK INT32 HalGetRtcTime(UINT64 *usec)
{
    UINT64 ticks;
    ticks = LOS_TickCountGet();

    *usec = (UINT64)(ticks*1000);

    return LOS_OK;
}

WEAK INT32 HalGetRtcTimeZone(INT32 *timeZone)
{
    return LOS_OK;
}


#if (LOSCFG_KERNEL_PRINTF != 0)
extern void *_flash_text_start;
extern void *_flash_text_end;
extern void *_itcm_start;
extern void *_itcm_end;
#define BLE_ROM_CODE_START  0x0000f000
#define BLE_ROM_CODE_END    0x0001dfc4

LITE_OS_SEC_TEXT_MINOR UINT32 OsIsExeAddr(UINTPTR addr)
{
    if ((addr >= (UINT32)&_flash_text_start) && (addr <= (UINT32)&_flash_text_end)) {
        return TRUE;
    } else if ((addr >= (UINT32)&_itcm_start) && (addr <= (UINT32)&_itcm_end)) {
       return TRUE;
    } else if ((addr >= BLE_ROM_CODE_START) && (addr <= BLE_ROM_CODE_END)) {
       return TRUE;
    }
    return FALSE;
}
#endif


/*****************************************************************************
 Function    : OsGetAllTskInfoEx
 Description : Get all task info more than OsGetAllTskInfo.
 Input       : None
 Output      : None
 Return      : None
 *****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 OsGetAllTskInfoEx(VOID)
{
#if (LOSCFG_KERNEL_PRINTF != 0)
    LosTaskCB    *taskCB = (LosTaskCB *)NULL;
    UINT32       loopNum;
    UINT32       semID;
    UINT32       debugStackDepth = 500;

    PRINT_ERR("\n---------------------- Task Stack Begin ----------------------\n");
    for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
        taskCB = (((LosTaskCB *)g_taskCBArray) + loopNum);
        if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
            continue;
        }

        PRINT_ERR("Task %s:\n", taskCB->taskName);
        for(UINT32 stk = (UINT32)(UINTPTR)taskCB->stackPointer, index = 0; stk <= (taskCB->topOfStack + taskCB->stackSize) && index < debugStackDepth; stk += 4)
        {
            if(OsIsExeAddr(*(UINT32*)stk))
                PRINT_ERR("[%08x]:0x%x\n", stk, *(UINT32*)stk);
            index++;
        }
        PRINT_ERR("\n\n\n");
    }

    PRINT_ERR("---------------------- Task Stack End ----------------------\n");
#endif
    return LOS_OK;
}

extern void  *_sp_start;
extern void  *_sp;
void LOS_exception_stack_print(unsigned int cur_sp)
{
    int i = 0;
    UINT32 *sp = (UINT32 *)cur_sp;
    printf("========== Stack info ==========\n");
    if (((sp >= __los_heap_addr_start__) && ((sp + 256) <= __los_heap_addr_end__)) ||
        ((sp >= (&_sp_start)) || ((sp + 256) <= (&_sp)))) {
        for (i = 0; i < 64; i+=4) {
            printf("stack(0x%08X): 0x%08X 0x%08X 0x%08X 0x%08X\n", ((UINT32)sp) + i * 4,
                sp[i], sp[i+1], sp[i+2], sp[i+3]);
        }
    } else {
        printf("stack pointer is invalid:0x%08X\n", (UINT32)sp);
    }
}
